<?php
/**
 * 缓存引擎抽象
 *
 * @since 1.0
 * @package if
 * @subpackage module.cache
 */
abstract class IAbstractCacheEngine extends IObject implements  ICacheEngine {
	private $settings;
	
	function __construct() {
		$this->init();
	}
	
	function init(array $settings = null) {
		$this->settings = $settings;
	}
	
	function settings() {
		return $this->settings;
	}
	
	function gc() {
		return $this->clear(true);
	}
	
	function value($key) {
		$entry = $this->entry($key);
		if ($entry) {
			return $entry->value();
		}
		return null;
	}
	
	/**
	 * 读取cache值
	 *
	 * @param string $key 键
	 * @return mixed
	 * @since 1.0.2
	 */
	function read($key) {
		return $this->value($key);
	}
	
	function write($key, $value, $ttl = 3600, $maxAge = 0) {
		return $this->writeWithTags(array(), $key, $value, $ttl, $maxAge);
	}	
	
	function writeWithTags($tags, $key, $value, $ttl = 3600, $maxAge = 0) {
		$entry = new ICacheEntry();
		$entry->setEngine($this);
		$entry->setTags($tags);
		$entry->setKey($key);
		$entry->setValue($value);
		$entry->setModified($this->_time());
		$entry->setTtl($ttl);
		$entry->setValue($value);
		if ($maxAge > 0) {
			$entry->setMaxAge($maxAge);
		}
		$array = $entry->asArray();
		return $this->writeEntry($entry);
	}
	
	function writeEntry(ICacheEntry $entry) {
		if ($this->_writeEntry($entry)) {
			$entry->setEngine($this);
			
			//保存tag
			$tags = $entry->tags();
			if (!empty($tags)) {
				$tagIds = array();
				foreach ($tags as $tag) {
					$tagkey = "TAG$$$" . $tag;
					$tagId = $this->read($tagkey);
					if (!$tagId) {
						$tagId = microtime(true);
						$this->write($tagkey, $tagId, 365 * 86400);
					}
					$tagIds[] = $tagId;
				}
				$entry->setTagIds($tagIds);
				$this->_writeEntry($entry);
			}
			
			return true;
		}
		return false;
	}
	
	function entry($key) {
		$entry = $this->_entry($key);
		if ($entry) {
			$entry->setEngine($this);
		}
		return $entry;
	}
	
	function deleteTag($tag) {
		if (!is_array($tag)) {
			$tag = preg_split("/[\s,;]+/", $tag);
		}
		$ret = true;
		foreach ($tag as $_tag) {
			if (!$this->delete("TAG$$$" . $_tag)) {
				$ret = false;
			}
		}
		return $ret;
	}
	
	abstract function _writeEntry(ICacheEntry $entry);
	abstract function _entry($key);
}

?>